package com.unionftech.baselibrary.network

import android.annotation.SuppressLint
import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
import okhttp3.OkHttpClient
import okhttp3.Protocol
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import retrofit2.mock.BehaviorDelegate
import retrofit2.mock.MockRetrofit
import retrofit2.mock.NetworkBehavior
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.Collections
import java.util.concurrent.TimeUnit
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSession
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

class RetrofitClient private constructor() {

    private val trustManager: X509TrustManager =
        @SuppressLint("CustomX509TrustManager") object : X509TrustManager {
            @SuppressLint("TrustAllX509TrustManager")
            override fun checkClientTrusted(x509Certificates: Array<X509Certificate>, s: String) {
            }

            @SuppressLint("TrustAllX509TrustManager")
            override fun checkServerTrusted(x509Certificates: Array<X509Certificate>, s: String) {
            }

            override fun getAcceptedIssuers(): Array<X509Certificate?> {
                return arrayOf()
            }
        }

    @SuppressLint("TrulyRandom")
    private fun createSSLSocketFactory(): SSLSocketFactory? {
        var sSLSocketFactory: SSLSocketFactory? = null
        try {
            val sc = SSLContext.getInstance("SSL")
            sc.init(
                null, getTrustManager(), SecureRandom()
            )
            sSLSocketFactory = sc.socketFactory
        } catch (e: Exception) {
        }
        return sSLSocketFactory
    }

    //获取TrustManager
    private fun getTrustManager(): Array<TrustManager> {
        //就是把下面这个X509TrustManager更换一下
        val trustAllCerts = arrayOf<TrustManager>(trustManager)
        return trustAllCerts
    }

    private class TrustAllHostnameVerifier : HostnameVerifier {
        @SuppressLint("BadHostnameVerifier")
        override fun verify(hostname: String, session: SSLSession): Boolean {
            return true
        }
    }

    companion object {
        /**
         * 网络请求的BASE_URL在Map中的key
         */
        const val KEY_BASE_URL = "base_url"
        private lateinit var mINetWork: INetWork
        private lateinit var mRetrofit: Retrofit
        private lateinit var mNoTokenInterceptorRetrofit: Retrofit
        private lateinit var mMockRetrofit: MockRetrofit

        //连接超时时间 单位：秒
        private const val CONNECT_TIMEOUT = 10L

        //读数据超时时间 单位：秒
        private const val READ_TIMEOUT = 10L

        //写数据超时时间 单位：秒
        private const val WRITE_TIMEOUT = 10L

        @JvmStatic
        fun init(netWork: INetWork) {
            mINetWork = netWork
        }

        @JvmStatic
        fun getInstance() = SingletonHolder.INSTANCE

    }


    private object SingletonHolder {
        val INSTANCE = RetrofitClient()
    }

    init {
        mRetrofit = Retrofit.Builder().client(getOkHttpClient())
            .addCallAdapterFactory(CoroutineCallAdapterFactory())
            .addConverterFactory(ScalarsConverterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(mINetWork.getUrlMap()[KEY_BASE_URL] ?: "").build()

        mNoTokenInterceptorRetrofit = Retrofit.Builder().client(getOkHttpClientNoTokenInterceptor())
            .addCallAdapterFactory(CoroutineCallAdapterFactory())
            .addConverterFactory(ScalarsConverterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(mINetWork.getUrlMap()[KEY_BASE_URL] ?: "").build()

        mMockRetrofit = MockRetrofit.Builder(
            Retrofit.Builder().baseUrl("https://www.xxxx.com/")
                .addCallAdapterFactory(CoroutineCallAdapterFactory())
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create()).build()
        ).networkBehavior(NetworkBehavior.create().also {
            it.setDelay(1000, TimeUnit.MILLISECONDS)
            it.setErrorPercent(0)
            it.setFailurePercent(0)
        }).build()
    }


    private fun getOkHttpClient(): OkHttpClient {
        val builder = OkHttpClient.Builder()
        builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).pingInterval(1, TimeUnit.SECONDS)
            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
            .retryOnConnectionFailure(true)
            .protocols(Collections.singletonList(Protocol.HTTP_1_1)) // 强制使用 HTTP/1.1
        createSSLSocketFactory()?.let {
            builder.sslSocketFactory(it, trustManager)
                .hostnameVerifier(TrustAllHostnameVerifier())
        }
        if (mINetWork.getInterceptors() != null) {
            for (interceptor in mINetWork.getInterceptors()!!) {
                builder.addInterceptor(interceptor)
            }
        }
        builder.addInterceptor(getHttpLoggingInterceptor())
        return builder.build()
    }

    private fun getOkHttpClientNoTokenInterceptor(): OkHttpClient {
        val builder = OkHttpClient.Builder()
        builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).pingInterval(1, TimeUnit.SECONDS)
            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS).retryOnConnectionFailure(true)
            .protocols(Collections.singletonList(Protocol.HTTP_1_1)) // 强制使用 HTTP/1.1
            .addInterceptor(getHttpLoggingInterceptor())
        return builder.build()
    }

    private fun getHttpLoggingInterceptor(): HttpLoggingInterceptor {
        val interceptor = HttpLoggingInterceptor { msg ->
            mINetWork.getHttpLogPrint(msg)
        }
        interceptor.level = HttpLoggingInterceptor.Level.BODY
        return interceptor
    }

    fun getNetWork(): INetWork {
        return mINetWork
    }

    /**
     * 创建service
     * @param service Class<T> 需要创建的service
     * @return T Service实例
     */
    fun <T> create(service: Class<T>): T {
        return mRetrofit.create(service)
    }

    /**
     * 创建service 没有刷新Token的拦截
     * @param service Class<T> 需要创建的service
     * @return T Service实例
     */
    fun <T> createNoTokenInterceptor(service: Class<T>): T {
        return mNoTokenInterceptorRetrofit.create(service)
    }

    /**
     * 创建service
     * @param service Class<T> 需要创建的service
     * @param baseUrl String 自定义baseUrl
     * @return T Service实例
     */
    fun <T> createBaseUrl(service: Class<T>, baseUrl: String): T {
        val retrofit = Retrofit.Builder().client(getOkHttpClient())
            .addCallAdapterFactory(CoroutineCallAdapterFactory())
            .addConverterFactory(ScalarsConverterFactory.create())
            .addConverterFactory(GsonConverterFactory.create()).baseUrl(baseUrl).build()
        return retrofit.create(service)
    }

    /**
     * 获取Mock 的 BehaviorDelegate
     */
    fun <T> createMock(service: Class<T>): BehaviorDelegate<T> {
        return mMockRetrofit.create(service)
    }
}